package com.zz.ecommerce.fileupload;

import com.zz.ecommerce.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
public class UploadFileService {

    @Autowired
    private UploadFileDao uploadFileDao;
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Value("${upload.file.path}")
    String defaultPath = "F:/meng/tmp";

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 默认路径保存文件
     *
     * @param multipartFile
     * @return
     * @throws IOException
     */
    public UploadFile saveFile(final MultipartFile multipartFile) throws IOException {
        return saveFile(multipartFile, defaultPath);
    }

    /**
     * 保存文件
     *
     * @param multipartFile
     * @return
     * @throws IOException
     */
    public UploadFile saveFile(final MultipartFile multipartFile, String path) throws IOException {
        String fileId = saveFileToDB(multipartFile.getOriginalFilename(), path, String.valueOf(multipartFile.getSize()));
        saveFileToDisk(multipartFile, path, fileId);
        UploadFile file = new UploadFile();
        List<UploadFile> listfile = uploadFileDao.queryFilesById(fileId);
        if (!CollectionUtils.isEmpty(listfile)) {
            file = listfile.get(0);
        }
        return file;
    }

    /**
     * 把文件保存到磁盘上
     *
     * @return
     */
    public boolean saveFileToDisk(final MultipartFile multipartFile, final String path, final String fileId)
            throws IOException {
        String suffixName = ZzStringUtil.getFileSuffix(multipartFile.getOriginalFilename());
        if (StringUtils.isNotEmpty(suffixName)) {
            File dir = new File(path);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            String fileName = path + "/" + fileId + "." + suffixName;
            OutputStream outputStream = null;
            try {
                outputStream = new BufferedOutputStream(new FileOutputStream(new File(fileName)));
                outputStream.write(multipartFile.getBytes());
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                logger.error("保存文件失败", e);
                if (null != outputStream) {
                    outputStream.close();
                }
                throw e;
            }
        }
        return true;
    }

    /**
     * 把文件保存到数据库里
     *
     * @param filePath
     * @param fileName
     * @return
     */
    public String saveFileToDB(final String fileName, final String filePath, final String fileSize) {
        String fileId = uploadFileDao.getSeqFileId();
        uploadFileDao.insertFile(fileId, filePath, fileName, fileId + "." + ZzStringUtil.getFileSuffix(
                fileName), fileSize);
        return fileId;
    }

    public String getUploadFilePath(String fileName) {
        return defaultPath + File.separator + fileName;
    }


    /**
     * 保存文件:接口调用上传附件时使用
     *
     * @param file             文件字节内容
     * @param originalFileName 原始文件名，包含文件类型后缀
     * @return
     * @throws IOException
     */
    public UploadFile saveFile(byte[] file, String originalFileName) throws IOException {
        String fileId = saveFileToDB(originalFileName, defaultPath, String.valueOf(file.length));
        uploadFileDao.updateFile(Long.parseLong(fileId), file);

        String suffixName = ZzStringUtil.getFileSuffix(originalFileName);
        if (StringUtils.isNotEmpty(suffixName)) {
            File dir = new File(defaultPath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            String fileName = defaultPath + "/" + fileId + "." + suffixName;
            OutputStream outputStream = null;
            try {
                outputStream = new BufferedOutputStream(new FileOutputStream(new File(fileName)));
                outputStream.write(file);
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                logger.error("保存文件失败", e);
                if (null != outputStream) {
                    outputStream.close();
                }
                throw e;
            }
        }

        UploadFile uploadFile = new UploadFile();
        List<UploadFile> listfile = uploadFileDao.queryFilesById(fileId);
        if (!CollectionUtils.isEmpty(listfile)) {
            uploadFile = listfile.get(0);
        }
        return uploadFile;
    }

    /**
     * 文件exl导入
     *
     * @param file
     * @param className
     * @param key
     * @return
     * @throws ClassNotFoundException
     */
    @Transactional(readOnly = false)
    public String doTemplateUpload(MultipartFile file, String className, String key, HttpSession session, String type)
            throws ClassNotFoundException {
        Class aClass = Class.forName(className);
        return importTemplateFile(file, aClass, key, session, type);
    }

    private String importTemplateFile(MultipartFile file, Class clasz, String key, HttpSession session, String type) {
        String[] properties = CommonUtil.getProperties(clasz);
        String reMsg = "";
        try {
            List<Object> beanList = ExcelReadHelper.excelReadStream(file, properties, clasz);
            List<Object[]> batch = new ArrayList<>();
            if (null != beanList && beanList.size() > 0) {
                //excel格式数据校验
//                reMsg = UploadValidateUtils.checkUpload(beanList, clasz, key);
                if (StringUtils.isNotEmpty(reMsg)) {
                    return reMsg;
                }
                for (Object vo : beanList) {
                    Object[] values = getValues(vo, session, type);
                    batch.add(values);
                }
                jdbcTemplate.batchUpdate(getSqlValues(clasz, key), batch);
            } else {
                reMsg = "导入excel数据不能为空!";
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("", e);
            reMsg = "数据插入异常，请查看导入数据是否存在已经存在,如无问题请联系系统管理员!";
        }
        return reMsg;
    }

    private Object[] getValues(Object obj, HttpSession session, String type) {
        List<String> list = new ArrayList<>();
        list.add(UUID.randomUUID().toString());
        list.add(SessionUtil.getOrganizationId(session));
        list.add(SessionUtil.getOperator(session));
        list.add(type);
        list.add("E1");
        Field fields[] = obj.getClass().getDeclaredFields();
        Object value = "";
        String valueTrim = "";
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                value = field.get(obj);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            field.setAccessible(true);
            if (null != field.getAnnotation(SqlType.class) && field.getAnnotation(SqlType.class).inTemplate()) {
                if ("date".equals(field.getAnnotation(SqlType.class).type())) {
                    value = DateUtils.strFormatDateStr((String) value, field.getAnnotation(SqlType.class).format());
                }
                valueTrim = String.valueOf(value);

                if (StringUtils.isEmpty(valueTrim)) {
                    valueTrim = "";
                }
                list.add(valueTrim.trim());
            }
        }
        final int size = list.size();
        return list.toArray(new String[size]);
    }

    private String getSqlValues(Class obj, String key) {
        StringBuffer buffer = new StringBuffer("INSERT INTO ");
        buffer.append(key);
        StringBuffer fieilds = new StringBuffer("(ID, ORG_ID, OPER_ID, BUSINESS_TYPE,STATUS,");
        StringBuffer values = new StringBuffer("VALUES(?,?,?,?,?,");
        Field fields[] = obj.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String name = field.getName();
            if (null != field.getAnnotation(SqlType.class)) {
                //增加defaultValue值的判断
                if (StringUtils.isNotEmpty(field.getAnnotation(SqlType.class).defaultValue())) {
                    fieilds.append(ZzStringUtil.transLateUpper2UnderLine(name) + ",");
                    values.append(field.getAnnotation(SqlType.class).defaultValue() + ",");
                } else if (field.getAnnotation(SqlType.class).inTemplate() &&
                        !"date".equals(field.getAnnotation(SqlType.class).type())) {
                    fieilds.append(ZzStringUtil.transLateUpper2UnderLine(name) + ",");
                    values.append("?,");
                } else if (field.getAnnotation(SqlType.class).inTemplate() &&
                        "date".equals(field.getAnnotation(SqlType.class).type())) {
                    fieilds.append(ZzStringUtil.transLateUpper2UnderLine(name) + ",");
                    values.append("to_date(?, '" + field.getAnnotation(SqlType.class).format() + "'),");
                }
            }
        }
        buffer.append(fieilds.substring(0, fieilds.length() - 1 > 0 ? fieilds.length() - 1 : 0)).append(")");
        buffer.append(values.substring(0, values.length() - 1 > 0 ? values.length() - 1 : 0)).append(")");
        return buffer.toString();
    }
}
